﻿using Cyss.Core;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq.Expressions;
using System.Text;

namespace System.Linq
{
    public static class LinqExtensions
    {
        public static string GetPropertyName<TModel, TResult>(this Expression<Func<TModel, TResult>> expr)
        {
            var rtn = "";
            if (expr.Body is UnaryExpression)
            {
                rtn = ((MemberExpression)((UnaryExpression)expr.Body).Operand).Member.Name;
            }
            else if (expr.Body is MemberExpression)
            {
                rtn = ((MemberExpression)expr.Body).Member.Name;
            }
            else if (expr.Body is ParameterExpression)
            {
                rtn = ((ParameterExpression)expr.Body).Type.Name;
            }
            return rtn;
        }

        public static string GetPropertieDisplay<TModel, TResult>(this Expression<Func<TModel, TResult>> expr)
        {
            var rtn = "";
            if (expr.Body is UnaryExpression)
            {
                rtn = ((MemberExpression)((UnaryExpression)expr.Body).Operand).Member.Name;
            }
            else if (expr.Body is MemberExpression)
            {
                rtn = ((MemberExpression)expr.Body).Member.Name;
            }
            else if (expr.Body is ParameterExpression)
            {
                rtn = ((ParameterExpression)expr.Body).Type.Name;
            }
            return typeof(TModel).GetCacheNamedMemberAccessors().FirstOrDefault(x => x.ProjectName==rtn)?.ProjectDisplayName;
        }



        public static IEnumerable<T> GetList<T>(this DataTable dataTable) where T : new()
        {
            List<T> list = new List<T>();
            var propertyInfos = typeof(T).GetProperties();
            int rowIndex = 0;
            foreach (DataRow row in dataTable.Rows)
            {
                rowIndex++;
                T model = new T();
                foreach (var pro in propertyInfos)
                {
                    var proName = pro.Name;
                    var excelAttribute = pro.GetCustomAttributes(typeof(ExcelAttribute), true).FirstOrDefault() as ExcelAttribute;
                    if (excelAttribute != null)
                    {
                        proName = excelAttribute.ColName;
                    }
                    if (!row.Table.Columns.Contains(proName))
                    {
                        continue;
                    }
                    var value = row[proName];
                    if (value.GetType() == typeof(System.DBNull) || string.IsNullOrWhiteSpace(value.ToString()))
                    {
                        continue;
                    }
                    try
                    {
                        value = value.ToString().Trim();
                        switch (pro.PropertyType.GetTypeCode())
                        {
                            case TypeCode.Boolean:
                                if (value.ToString() == "1" || value.ToString() == "是")
                                {
                                    value = true;
                                }
                                if (value.ToString() == "0" || value.ToString() == "否")
                                {
                                    value = false;
                                }
                                break;
                            case TypeCode.Decimal:
                                value = value.ToString().Replace("$", "").Trim();
                                value= Convert.ChangeType(value, pro.PropertyType);
                                break;
                            case TypeCode.Int16:
                            case TypeCode.Int32:
                            case TypeCode.Int64:
                                if (pro.GetType().IsNullableType())
                                {
                                    value=Convert.ChangeType(value, pro.PropertyType.GenericTypeArguments[0]);
                                }
                                else
                                {
                                    value=Convert.ChangeType(value, pro.PropertyType);
                                }
                                break;
                            case TypeCode.DateTime:
                                value = GetDateTimeValue(value, excelAttribute.FormatString);
                                break;
                            default:
                                value=Convert.ChangeType(value, pro.PropertyType);
                                break;
                        }
                        pro.SetValue(model, value);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception($"第{rowIndex}行列{proName}值{value.ToString()}读取失败" + ex.Message);
                    }
                }
                list.Add(model);
            }
            return list;
        }

        private static object GetDateTimeValue(object value, string FormatString = "")
        {
            if (!string.IsNullOrWhiteSpace(FormatString))
            {
                return DateTime.ParseExact(value.ToString(), FormatString, System.Globalization.CultureInfo.CurrentCulture);
            }
            var strValue = value.ToString().Replace("/", "-");
            DateTime dateTime;
            if (strValue.Contains("EST"))
            {
                value=value.ToString().Replace("EST", "").Trim();
                dateTime = DateTime.Parse(value.ToString()).AddHours(5).AddHours(8);
            }
            else if (strValue.Contains("CST"))
            {
                value=value.ToString().Replace("CST", "").Trim();
                dateTime = DateTime.Parse(value.ToString()).AddHours(6).AddHours(8);

            }
            else if (strValue.Contains("MST"))
            {
                value=value.ToString().Replace("MST", "").Trim();
                dateTime = DateTime.Parse(value.ToString()).AddHours(7).AddHours(8);
            }
            else if (strValue.Contains("PST"))
            {
                value=value.ToString().Replace("PST", "").Trim();
                dateTime = DateTime.Parse(value.ToString()).AddHours(8).AddHours(8);
            }
            else if (strValue.Contains("AKST"))
            {
                value=value.ToString().Replace("AKST", "").Trim();
                dateTime = DateTime.Parse(value.ToString()).AddHours(9).AddHours(8);
            }
            else if (strValue.Contains("HST"))
            {
                value=value.ToString().Replace("HST", "").Trim();
                dateTime = DateTime.Parse(value.ToString()).AddHours(10).AddHours(8);
            }
            else
            {
                dateTime = DateTime.Parse(value.ToString());
            }
            DateTime.SpecifyKind(dateTime, DateTimeKind.Local);
            return dateTime; ;
        }

    }
}
